<template>
  <div ref="editorContainer" class="editor-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'

import * as monaco from 'monaco-editor'

// 如果项目不使用这些，可以去掉相关语言的载入
self.MonacoEnvironment = {
  getWorker(_: string, label: string) {
    if (label === 'json') {
      return new JsonWorker()
    }
    if (['css', 'scss', 'less'].includes(label)) {
      return new CssWorker()
    }
    if (['html', 'handlebars', 'razor'].includes(label)) {
      return new HtmlWorker()
    }
    if (['typescript', 'javascript'].includes(label)) {
      return new TsWorker()
    }
    return new EditorWorker()
  },
}

const editorContainer = ref<HTMLElement | null>(null)
let editor: monaco.editor.IStandaloneCodeEditor | null = null

onMounted(() => {
  // 注册一个新的语言text
  monaco.languages.register({
    id: 'text',
    aliases: ['txt', 'text'],
    mimetypes: ['text/plain'],
  })
  // 为text语言，注册一个tokenizer，用于解析文本
  monaco.languages.setMonarchTokensProvider('text', {
    tokenizer: {
      root: [
        [/[a-zA-Z]+/, 'identifier'],
        [/[0-9]+/, 'number'],
        [/\“.*\”/, 'string.url'], // 新增规则，匹配双引号之间的文字
      ],
    },
  })
  // 注册一个主题，用于设置编辑器的颜色
  monaco.editor.defineTheme('TextTheme', {
    base: 'vs-dark',
    inherit: true,
    rules: [
      { token: 'identifier', foreground: '008800' },
      { token: 'number', foreground: '0000ff' },
      { token: 'string.url', foreground: 'ff6600', fontStyle: 'underline' },
    ],
    colors: {}, // 设置主题颜色，这里设置的颜色是默认的
  })
  // 注册一个completionProvider，用于自动补全
  monaco.languages.registerCompletionItemProvider('text', {
    provideCompletionItems: (model, position) => {
      const word = model.getWordUntilPosition(position)
      const range = new monaco.Range(
        position.lineNumber,
        word.startColumn,
        position.lineNumber,
        word.endColumn
      )
      return {
        suggestions: [
          {
            label: 'myKeyword1',
            kind: monaco.languages.CompletionItemKind.Keyword,
            insertText: 'myKeyword1',
            range: range,
          },
          {
            label: 'myKeyword2',
            kind: monaco.languages.CompletionItemKind.Keyword,
            insertText: 'myKeyword2',
            range: range,
          },
        ],
      }
    },
  })
  // 创建编辑器实例
  if (editorContainer.value) {
    editor = monaco.editor.create(editorContainer.value, {
      minimap: { enabled: false }, // 是否启用预览图
      value: 'Hello, world!, “中文测试”，中文测试',
      language: 'text',
      automaticLayout: true, // 自适应布局
      theme: 'TextTheme',
      folding: true, // 是否启用代码折叠
      renderLineHighlight: 'gutter', // 当前行突出显示方式 none line gutter all
      quickSuggestions: true, // 快速建议
    })
    //  注册一个自定义的action，用于格式化代码
    editor.addAction({
      // 唯一标识符
      id: 'my-unique-id',
      // 用户可见的标签
      label: '格式化代码',
      // 可选的快捷键
      keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyM],
      // 执行条件
      // precondition: null,
      // 快捷键的调度规则
      // keybindingContext: null,
      // 菜单组ID
      contextMenuGroupId: 'navigation',
      // 菜单顺序
      contextMenuOrder: 1.5,
      // 触发操作时执行的方法
      run: () => {
        const formatAction = editor?.getAction('editor.action.formatDocument')
        if (formatAction) formatAction.run()
      },
    })
  }
})

onBeforeUnmount(() => {
  editor?.dispose()
})
</script>

<style scoped>
.editor-container {
  width: 100%;
  height: 100%;
}
</style>
